﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Gmantis.Controls
{
    public class DockPanel : Panel
    {
        // Fields
        public static readonly DependencyProperty DockProperty = DependencyProperty.RegisterAttached("Dock", typeof(Dock), typeof(DockPanel), new PropertyMetadata(new PropertyChangedCallback(DockPanel.OnDockPropertyChanged)));
        public static readonly DependencyProperty LastChildFillProperty = DependencyProperty.Register("LastChildFill", typeof(bool), typeof(DockPanel), new PropertyMetadata(true, new PropertyChangedCallback(DockPanel.OnLastChildFillPropertyChanged)));

        // Methods
        public DockPanel()
        {
            SetCustomDefaultValues();
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            int count = base.Children.Count;
            int num2 = count - (this.LastChildFill ? 1 : 0);
            double x = 0.0;
            double y = 0.0;
            double num5 = 0.0;
            double num6 = 0.0;
            for (int i = 0; i < count; i++)
            {
                UIElement element = base.Children[i];
                if (element != null)
                {
                    Size desiredSize = element.DesiredSize;
                    Rect finalRect = new Rect(x, y, Math.Max((double)0.0, (double)(finalSize.Width - (x + num5))), Math.Max((double)0.0, (double)(finalSize.Height - (y + num6))));
                    if (i < num2)
                    {
                        switch (this.GetDock(element))
                        {
                            case Dock.Left:
                                x += desiredSize.Width;
                                finalRect.Width = desiredSize.Width;
                                break;

                            case Dock.Right:
                                num5 += desiredSize.Width;
                                finalRect.X = Math.Max((double)0.0, (double)(finalSize.Width - num5));
                                finalRect.Width = desiredSize.Width;
                                break;

                            case Dock.Top:
                                y += desiredSize.Height;
                                finalRect.Height = desiredSize.Height;
                                break;

                            case Dock.Bottom:
                                num6 += desiredSize.Height;
                                finalRect.Y = Math.Max((double)0.0, (double)(finalSize.Height - num6));
                                finalRect.Height = desiredSize.Height;
                                break;
                        }
                    }
                    element.Arrange(finalRect);
                }
            }
            return finalSize;
        }

        public static Dock GetDock(DependencyObject element)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }
            return (Dock)element.GetValue(DockProperty);
        }

        private Dock GetDock(UIElement element)
        {
            object obj2 = element.GetValue(DockProperty);
            if (obj2 == null)
            {
                return Dock.Left;
            }
            return (Dock)obj2;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            double num = 0.0;
            double num2 = 0.0;
            double num3 = 0.0;
            double num4 = 0.0;
            for (int i = 0; i < base.Children.Count; i++)
            {
                UIElement element = base.Children[i];
                if (element != null)
                {
                    Size size = new Size(Math.Max((double)0.0, (double)(availableSize.Width - num3)), Math.Max((double)0.0, (double)(availableSize.Height - num4)));
                    element.Measure(size);
                    Size desiredSize = element.DesiredSize;
                    switch (this.GetDock(element))
                    {
                        case Dock.Left:
                        case Dock.Right:
                            num2 = Math.Max(num2, num4 + desiredSize.Height);
                            num3 += desiredSize.Width;
                            break;

                        case Dock.Top:
                        case Dock.Bottom:
                            num = Math.Max(num, num3 + desiredSize.Width);
                            num4 += desiredSize.Height;
                            break;
                    }
                }
            }
            num = Math.Max(num, num3);
            return new Size(num, Math.Max(num2, num4));
        }

        private static void OnDockPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement reference = d as FrameworkElement;
            if (reference != null)
            {
                DockPanel parent = VisualTreeHelper.GetParent(reference) as DockPanel;
                if ((parent != null) && !object.Equals(e.OldValue, e.NewValue))
                {
                    parent.InvalidateMeasure();
                }
            }
        }

        private static void OnLastChildFillPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DockPanel panel = d as DockPanel;
            bool oldValue = (bool)e.OldValue;
            bool newValue = (bool)e.NewValue;
            if (newValue != oldValue)
            {
                panel.InvalidateMeasure();
            }
        }

        private void SetCustomDefaultValues()
        {
        }

        public static void SetDock(DependencyObject element, Dock value)
        {
            if (element == null)
                throw new ArgumentNullException("element");

            element.SetValue(DockProperty, value);
        }

        // Properties
        public bool LastChildFill
        {
            get { return (bool)GetValue(LastChildFillProperty); }
            set { SetValue(LastChildFillProperty, value); }
        }
    }

    public enum Dock : byte
    {
        Bottom = 3,
        Left = 0,
        Right = 1,
        Top = 2
    }
}
